package com.ushine.web.component.redis;

import com.ushine.web.component.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * @Author: yls
 * @Date: 2022/02/13 23:20
 * @Description: redis 分布式锁模板封装（单机也可用）
 * @Version 1.0
 */
@Slf4j
@Service
public class RedisLockServiceImpl {

    @Resource
    private RedisLockConfig redisLockConfig;


    /**
     * 功能描述:
     * 〈 不带返回值的分布式锁实现 〉
     *
     * @param lockName    锁名称
     * @param businessId  业务ID
     * @param voidHandler 业务处理
     * @return : void
     * @author : yls
     * @date : 2022/02/13 23:32
     * @throws ServiceException 服务端自定义异常
     */
    @Transactional(rollbackFor = Exception.class)
    public void lock(String lockName, Object businessId, VoidHandler voidHandler) throws ServiceException {
        RLock lock = redisLockConfig.getLock(lockName, businessId);
        try {
            lock.lock();
            voidHandler.execute();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 功能描述:
     * 〈 带返回值的分布式锁实现 〉
     *
     * @param lockName      锁名称
     * @param businessId    业务ID
     * @param returnHandler 业务处理
     * @return : void
     * @author : yls
     * @date : 2022/02/13 23:32
     * @throws ServiceException 服务端自定义异常
     */
    @Transactional(rollbackFor = Exception.class)
    public <T> T lock(String lockName, Object businessId, ReturnHandler<T> returnHandler) throws ServiceException {
        RLock lock = redisLockConfig.getLock(lockName, businessId);
        try {
            lock.lock();
            return returnHandler.execute();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 功能描述:
     * 〈 不带返回值的分布式锁实现 〉
     *
     * @param lockName    锁名称
     * @param businessId  业务ID
     * @param voidHandler 业务处理
     * @return : void
     * @author : yls
     * @date : 2022/02/13 23:32
     * @throws ServiceException 服务端自定义异常
     */
    @Transactional(rollbackFor = Exception.class)
    public void tryLock(String lockName, Object businessId, VoidHandler voidHandler) throws ServiceException {
        RLock lock = redisLockConfig.getLock(lockName, businessId);
        if (lock.tryLock()) {
            return;
        }

        try {
            lock.lock();
            voidHandler.execute();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 功能描述:
     * 〈 带返回值的分布式锁实现 〉
     *
     * @param lockName      锁名称
     * @param businessId    业务ID
     * @param returnHandler 业务处理
     * @return : void
     * @author : yls
     * @date : 2022/02/13 23:32
     * @throws ServiceException 服务端自定义异常
     */
    @Transactional(rollbackFor = Exception.class)
    public <T> T tryLock(String lockName, Object businessId, ReturnHandler<T> returnHandler) throws ServiceException {
        RLock lock = redisLockConfig.getLock(lockName, businessId);
        if (lock.tryLock()) {
            return null;
        }
        try {
            lock.lock();
            return returnHandler.execute();
        } finally {
            lock.unlock();
        }
    }

}
